From 71c0ba1f01b98770ec2c60cdb935ffb36c1830a9 Mon Sep 17 00:00:00 2001
From: joonhoekim <26rote@gmail.com>
Date: Mon, 8 Dec 2025 12:08:00 +0900
Subject: (김준회) 테이블 커스텀 훅 버전 생성
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 app/[lng]/test/table-v3/page.tsx | 188 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 188 insertions(+)
 create mode 100644 app/[lng]/test/table-v3/page.tsx

(limited to 'app/[lng]/test/table-v3/page.tsx')

diff --git a/app/[lng]/test/table-v3/page.tsx b/app/[lng]/test/table-v3/page.tsx
new file mode 100644
index 00000000..eccf7cff
--- /dev/null
+++ b/app/[lng]/test/table-v3/page.tsx
@@ -0,0 +1,188 @@
+"use client";
+
+import * as React from "react";
+import { useClientTable, ClientVirtualTable } from "@/components/client-table-v3";
+import { productColumns } from "../table-v2/columns";
+import { 
+  getProductTableData, 
+  getAllProducts, 
+  getProductTableDataWithGrouping, 
+  GroupInfo 
+} from "../table-v2/actions";
+import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
+import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
+import { Badge } from "@/components/ui/badge";
+import { ChevronDown, ChevronRight } from "lucide-react";
+
+// --- Components for Examples ---
+
+function ClientSideExample() {
+  const [products, setProducts] = React.useState<any[]>([]);
+  
+  // Load initial data once
+  React.useEffect(() => {
+    getAllProducts().then(setProducts);
+  }, []);
+
+  // Hook handles table state
+  const { table, isLoading } = useClientTable({
+    fetchMode: "client",
+    data: products,
+    columns: productColumns,
+    enablePagination: true,
+    enableGrouping: true,
+  });
+
+  return (
+    <Card>
+      <CardHeader>
+        <CardTitle>Pattern 1: Client-Side (V3)</CardTitle>
+        <CardDescription>
+          Uses `useClientTable` hook for simplified state management.
+        </CardDescription>
+      </CardHeader>
+      <CardContent className="h-[500px]">
+        <ClientVirtualTable 
+          table={table} 
+          isLoading={isLoading} 
+          enableUserPreset 
+          tableKey="v3-client-pattern" 
+        />
+      </CardContent>
+    </Card>
+  );
+}
+
+function ServerFactoryExample() {
+  // Hook handles everything: state, fetching, debouncing
+  const { table, isLoading } = useClientTable({
+    fetchMode: "server",
+    fetcher: getProductTableData,
+    columns: productColumns,
+    enablePagination: true,
+    enableUserPreset: true, // We can enable this in options too? No, hook doesn't care. Component cares.
+  });
+
+  return (
+    <Card>
+      <CardHeader>
+        <CardTitle>Pattern 2: Factory Service (V3)</CardTitle>
+        <CardDescription>
+          Zero boilerplate state management in the component.
+        </CardDescription>
+      </CardHeader>
+      <CardContent className="h-[500px]">
+        <ClientVirtualTable 
+          table={table} 
+          isLoading={isLoading} 
+          enableUserPreset 
+          tableKey="v3-server-pattern" 
+        />
+      </CardContent>
+    </Card>
+  );
+}
+
+function ServerGroupingExample() {
+  // Adapter for V2 fetcher signature to work with V3 hook
+  // The V2 action expects (state, expandedGroups), but V3 hook passes (state).
+  // We wrap it to extract expandedGroups from state.expanded.
+  const fetcher = React.useCallback((state: any) => {
+    const expanded = state.expanded || {};
+    // Convert TanStack ExpandedState { [key]: true } to string[]
+    const expandedKeys = Object.keys(expanded).filter(k => expanded[k]);
+    return getProductTableDataWithGrouping(state, expandedKeys);
+  }, []);
+
+  // Pattern 2-B support
+  const { 
+    table, 
+    isLoading, 
+    isServerGrouped, 
+    serverGroups, 
+    refresh, 
+  } = useClientTable({
+    fetchMode: "server",
+    fetcher,
+    columns: productColumns,
+    enablePagination: true,
+    enableGrouping: true,
+  });
+
+  // When serverGroups change (new grouping), reset expansion
+  // (In a real app, you might want to persist expansion logic in the fetcher wrapper or hook)
+  
+  return (
+    <Card>
+      <CardHeader>
+        <CardTitle>Pattern 2-B: Server Grouping (V3)</CardTitle>
+        <CardDescription>
+          Hook manages state, Component manages Custom Rendering for Groups.
+        </CardDescription>
+      </CardHeader>
+      <CardContent className="h-[500px] flex flex-col">
+        {/* We need the toolbar even in grouped mode */}
+         <div className="mb-4 p-2 border rounded bg-muted/20">
+            <p className="text-sm text-muted-foreground">
+               Group by a column (Category, Status, IsNew) to see server grouping.
+            </p>
+         </div>
+
+        {isServerGrouped ? (
+           <div className="overflow-auto border rounded-md p-4 space-y-2">
+              {serverGroups.map((group: GroupInfo) => (
+                <div key={group.groupKey} className="border rounded p-2">
+                   <div className="font-bold flex items-center gap-2">
+                     <Badge variant="outline">{String(group.groupValue)}</Badge>
+                     <span>({group.count})</span>
+                   </div>
+                   {/* Rows would go here */}
+                </div>
+              ))}
+           </div>
+        ) : (
+          <ClientVirtualTable 
+            table={table} 
+            isLoading={isLoading}
+            enableUserPreset
+            tableKey="v3-server-grouping"
+          />
+        )}
+      </CardContent>
+    </Card>
+  );
+}
+
+export default function TableV3Page() {
+  return (
+    <div className="container py-8 space-y-8">
+      <div>
+        <h1 className="text-3xl font-bold">ClientVirtualTable V3 DX Demo</h1>
+        <p className="text-muted-foreground">
+           Demonstrating the new `useClientTable` hook for improved Developer Experience.
+        </p>
+      </div>
+
+      <Tabs defaultValue="client">
+        <TabsList>
+           <TabsTrigger value="client">Client-Side</TabsTrigger>
+           <TabsTrigger value="server">Server Factory</TabsTrigger>
+           <TabsTrigger value="grouping">Server Grouping</TabsTrigger>
+        </TabsList>
+
+        <TabsContent value="client">
+           <ClientSideExample />
+        </TabsContent>
+
+        <TabsContent value="server">
+           <ServerFactoryExample />
+        </TabsContent>
+
+        <TabsContent value="grouping">
+           <ServerGroupingExample />
+        </TabsContent>
+      </Tabs>
+    </div>
+  );
+}
+
-- 
cgit v1.2.3

